/*
 * Copyright 2002-2019 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.springframework.aop;

import java.lang.reflect.Method;

/**
 * 是{@link Pointcut}的一部分。检查目标方法是否符合建议的条件。
 *
 *
 * MethodMatcher可以被评估<b>静态</b>或在<b>运行时</b>（动态）。
 * 静态匹配涉及方法和（可能）方法属性。
 * 动态匹配也使特定调用的参数可用，以及运行的任何影响以前的建议适用于连接点。
 *
 *
 * 如果一个实现从它的{@link #isRuntime()}中返回{@code false}，方法可以静态地进行评估，其结果将是相同的。
 * 方法，可以静态地进行评估，而且结果将是相同的对于这个方法的所有调用，无论其参数如何。
 * 这意味着如果{@link #isRuntime()}方法返回{@code false}，
 * 3-arg{@link #matches(java.lang.reflect.Method, Class, Object[])}方法将永远不会被调用。
 *
 *
 * 如果一个实现从它的2-arg中返回{@code true}，那么它的{@link #matches(java.lang.reflect.Method, Class)}方法返回
 * {@code true}，并且其{@link #isRuntime()}方法返回{@code true}，
 * 则3-arg {@link #matches(java.lang.reflect.Method, Class, Object[])}将被调用。
 * 方法将在相关建议的每次潜在执行之前立即被调用来决定建议是否应该运行。
 * 所有之前的建议，如拦截器链中早期的拦截器拦截器链中的所有先前的拦截器都会运行，
 * 因此它们所产生的任何状态变化都会在参数或ThreadLocal状态中产生的任何状态变化，在评估时都是可用的。
 *
 * 这个接口的具体实现通常应该提供适当的和{@link Object#equals(Object)}和{@link Object#hashCode()}的适当实现，
 * 以使匹配器能够用于缓存场景。
 * 以便允许匹配器用于缓存场景&mdash;
 * 		例如，在由CGLIB生成的代理中。
 *
 * @author Rod Johnson
 * @since 11.11.2003
 * @see Pointcut
 * @see ClassFilter
 */
public interface MethodMatcher {

	/**
	 * 执行静态检查给定方法是否匹配。
	 * 如果返回{@code false}或者{@link #isRuntime()}方法返回{@code false}，则不进行运行时检查。
	 * 方法返回{@code false}，则不进行运行时检查（也就是说，
	 * 没有{@link #matches(java.lang.reflect.Method, Class, Object[])}调用)将被调用。
	 * @param method 候选方法
	 * @param targetClass 目标类
	 * @return 该方法是否与静态匹配
	 */
	boolean matches(Method method, Class<?> targetClass);

	/**
	 * 这个MethodMatcher是动态的吗，也就是说，必须在{@link #matches(java.lang.reflect.Method, Class, Object[])}
	 * 方法在即使2-arg matches方法返回{@code true}，也必须在运行时对该方法进行最终调用？
	 * 可以在创建AOP代理时调用，并且不需要在每个方法调用前再次调用。在每个方法调用之前再次调用。
	 * @return 是否通过3-arg进行运行时匹配{@link #matches(java.lang.reflect.Method, Class, Object[])}方法的运行时匹配。
	 * 			如果通过静态匹配，则需要
	 */
	boolean isRuntime();

	/**
	 * 检查这个方法是否有一个运行时（动态）匹配。
	 * 这必须是静态匹配。
	 * 这个方法只有在2-arg匹配方法返回时才会被调用{@code true} 对于给定的方法和目标类，
	 * 并且如果{@link #isRuntime()}方法返回{@code true}。
	 * 调用紧接着建议的潜在运行，在建议链的任何建议链中的任何建议都已运行。
	 * @param method 候选方法
	 * @param targetClass 目标类
	 * @param args 方法的参数
	 * @return 是否有一个运行时间的匹配
	 * @see MethodMatcher#matches(Method, Class)
	 */
	boolean matches(Method method, Class<?> targetClass, Object... args);


	/**
	 * 匹配所有方法的经典实例。
	 */
	MethodMatcher TRUE = TrueMethodMatcher.INSTANCE;

}
